/*
	ViewGame.cpp
	(c)2000 Palestar, Richard Lyle
*/

#define INTERFACE_DLL
#include "Debug/Assert.h"
#include "File/FileDisk.h"
#include "Standard/StringBuffer.h"
#include "System/Keyboard.h"
#include "Game/NounUnit.h"
#include "World/NounTarget.h"
#include "Game/NounDropTarget.h"
#include "Game/NounBeacon.h"
#include "Game/NounCargo.h"
#include "Game/NounJumpGate.h"
#include "Game/CargoGadget.h"
#include "Game/NounStar.h"
#include "Game/VerbScrap.h"
#include "Game/VerbDisband.h"
#include "Game/VerbSetStructureActive.h"
#include "Game/VerbEnterOrbit.h"
#include "Game/VerbUseStructure.h"
#include "Game/VerbDistress.h"
#include "Game/VerbUnload.h"
#include "Game/VerbLoad.h"
#include "Game/VerbLockPlanet.h"
#include "Game/VerbApplyEnhancement.h"
//#include "Game/VerbTransferCredits.h"
#include "Game/VerbOrderUnit.h"
#include "Game/VerbOrderShip.h"
#include "Game/VerbUseSingleGadget.h"
#include "Game/VerbRepairGadget.h"
#include "Game/VerbUseMode.h"
#include "Game/VerbRemoveEnhancement.h"
#include "Game/StructureDefense.h"
#include "Game/StructureDepot.h"
#include "Game/StructurePort.h"
#include "Game/StructureShipyard.h"
#include "Game/GadgetShield.h"
#include "Game/GadgetArmor.h"
#include "Game/GadgetBeamWeapon.h"
#include "Game/GadgetSlot.h"
#include "Game/Resource.h"
#include "Interface/WindowObserve.h"
#include "Interface/TipHelp.h"
#include "Game/CargoEnhancement.h"
#include "Interface/ViewGame.h"


#include "Game/StructurePort.h"

//----------------------------------------------------------------------------

const float CHECK_FOR_COLLISION_TIME = 1.0f;
const float COLLISION_WARNING_TIME = 5.0f;

static Constant MAX_TARGET_RANGE( "MAX_TARGET_RANGE", 500000.0f );
ViewGame * ViewGame::m_pViewGame=NULL;
//----------------------------------------------------------------------------

IMPLEMENT_FACTORY( ViewGame, WindowView::View );
REGISTER_FACTORY_KEY( ViewGame, 4241436226245074821 );

ViewGame::ViewGame()
{
	m_Mode = TACTICAL;
	m_ChatMode = FACTION;
	m_pDoc = NULL;

	m_CameraFromNavigation = false;
}

//----------------------------------------------------------------------------

void ViewGame::onActivate()
{
	// set the view for tips
	ViewGame::m_pViewGame = this;
	//{{BEGIN_DATA_INIT
	DATA_MAP( m_pEnhancementWindow, WindowEnhancement, "EnhancementWindow" );
	DATA_MAP( m_pTipHelpBox, NodeWindow, "TipHelpWindow" );
	DATA_MAP( m_pTipHelpText, WindowText, "TipHelpText" );
	DATA_MAP( m_pTipHelpTitle, WindowText, "TipHelpTitle" );
	m_pMessageBoxCANCEL = WidgetCast<WindowButton>( window()->findNode( "MessageBoxCANCEL" ) );
	m_pMessageBoxOK = WidgetCast<WindowButton>( window()->findNode( "MessageBoxOK" ) );
	m_pMessageBox = WidgetCast<WindowText>( window()->findNode( "MessageBox" ) );
	m_pButtonCancelOrder = WidgetCast<WindowButton>( window()->findNode( "ButtonCancelOrder" ) );
	m_pPopupTargetButtons = WidgetCast<ButtonPopup>( window()->findNode( "PopupTargetButtons" ) );
	m_pButtonRightConsole = WidgetCast<WindowButton>( window()->findNode( "ButtonRightConsole" ) );
	m_pTargetFrame = WidgetCast<NodeWindow>( window()->findNode( "TargetFrame" ) );
	m_pLayoutTargetButtons = WidgetCast<NodeWindow>( window()->findNode( "LayoutTargetButtons" ) );
	m_pButtonShadow = WidgetCast<WindowButton>( window()->findNode( "ButtonShadow" ) );
	m_pButtonScoutMission = WidgetCast<WindowButton>( window()->findNode( "ButtonScoutMission" ) );
	m_pButtonDefendMission = WidgetCast<WindowButton>( window()->findNode( "ButtonDefendMission" ) );
	m_pButtonCaptureMission = WidgetCast<WindowButton>( window()->findNode( "ButtonCaptureMission" ) );
	m_pButtonAttackMission = WidgetCast<WindowButton>( window()->findNode( "ButtonAttackMission" ) );
	m_pButtonTarget = WidgetCast<WindowButton>( window()->findNode( "ButtonTarget" ) );
	m_pButtonYell = WidgetCast<WindowButton>( window()->findNode( "ButtonYell" ) );
	m_pButtonFaction = WidgetCast<WindowButton>( window()->findNode( "ButtonFaction" ) );
	m_pButtonFleet = WidgetCast<WindowButton>( window()->findNode( "ButtonFleet" ) );
	m_pButtonNextTarget = WidgetCast<WindowButton>( window()->findNode( "ButtonNextTarget" ) );
	m_pButtonUpTarget = WidgetCast<WindowButton>( window()->findNode( "ButtonUpTarget" ) );
	m_pButtonOrderRaze = WidgetCast<WindowButton>( window()->findNode( "ButtonOrderRaze" ) );
	m_pButtonOrderDefend = WidgetCast<WindowButton>( window()->findNode( "ButtonOrderDefend" ) );
	m_pButtonOrderAttack = WidgetCast<WindowButton>( window()->findNode( "ButtonOrderAttack" ) );
	m_pButtonNext = WidgetCast<WindowButton>( window()->findNode( "ButtonNext" ) );
	m_pButtonPrev = WidgetCast<WindowButton>( window()->findNode( "ButtonPrev" ) );
	m_pButtonRepairNow = WidgetCast<WindowButton>( window()->findNode( "ButtonRepairNow" ) );
	m_pButtonRepairLast = WidgetCast<WindowButton>( window()->findNode( "ButtonRepairLast" ) );
	m_pButtonAutoDefense = WidgetCast<WindowButton>( window()->findNode( "ButtonAutoDefense" ) );
	m_pButtonUseStructure = WidgetCast<WindowButton>( window()->findNode( "ButtonUseStructure" ) );
	m_pButtonApplyEnhancement = WidgetCast<WindowButton>( window()->findNode( "ButtonApplyEnhancement" ) );
	m_pButtonSendChat = WidgetCast<WindowButton>( window()->findNode( "ButtonSendChat" ) );
	m_pEditTransferCredits = WidgetCast<WindowEdit>( window()->findNode( "EditTransferCredits" ) );
	m_pWindowTransferCredits = WidgetCast<NodeWindow>( window()->findNode( "WindowTransferCredits" ) );
	m_pButtonTransferCredits = WidgetCast<WindowButton>( window()->findNode( "ButtonTransferCredits" ) );
	m_pButtonPlanet = WidgetCast<WindowButton>( window()->findNode( "ButtonPlanet" ) );
	m_pButtonUnlock = WidgetCast<WindowButton>( window()->findNode( "ButtonUnlock" ) );
	m_pButtonLock = WidgetCast<WindowButton>( window()->findNode( "ButtonLock" ) );
	m_pViewPlanet = WidgetCast<NodeWindow>( window()->findNode( "ViewPlanet" ) );
	m_pTargetButtons2 = WidgetCast<NodeWindow>( window()->findNode( "TargetButtons2" ) );
	m_pButtonJettison = WidgetCast<WindowButton>( window()->findNode( "ButtonJettison" ) );
	m_pButtonCamera = WidgetCast<WindowButton>( window()->findNode( "ButtonCamera" ) );
	m_pButtonContinue = WidgetCast<WindowButton>( window()->findNode( "ButtonContinue" ) );
	m_pButtonPause = WidgetCast<WindowButton>( window()->findNode( "ButtonPause" ) );
	m_pSignatureText = WidgetCast<WindowText>( window()->findNode( "SignatureText" ) );
	m_pSignatureBar = WidgetCast<BarHUD>( window()->findNode( "SignatureBar" ) );
	m_pRightConsole = WidgetCast<NodeWindow>( window()->findNode( "RightConsole" ) );
	m_pLeftConsole = WidgetCast<NodeWindow>( window()->findNode( "LeftConsole" ) );
	m_pChatEdit = WidgetCast<WindowEdit>( window()->findNode( "ChatEdit" ) );
	m_pHelpWindow = WidgetCast<NodeWindow>( window()->findNode( "HelpWindow" ) );
	m_pButtonDisband = WidgetCast<WindowButton>( window()->findNode( "ButtonDisband" ) );
	m_pButtonScrap = WidgetCast<WindowButton>( window()->findNode( "ButtonScrap" ) );
	m_pButtonLoad = WidgetCast<WindowButton>( window()->findNode( "ButtonLoad" ) );
	m_pButtonOrbit = WidgetCast<WindowButton>( window()->findNode( "ButtonOrbit" ) );
	m_pButtonFollow = WidgetCast<WindowButton>( window()->findNode( "ButtonFollow" ) );
	m_pTargetDescription = WidgetCast<WindowText>( window()->findNode( "TargetDescription" ) );
	m_pButtonNavigation = WidgetCast<WindowButton>( window()->findNode( "ButtonNavigation" ) );
	m_pButtonHelp = WidgetCast<WindowButton>( window()->findNode( "ButtonHelp" ) );
	m_pIncomingMessages = WidgetCast<NodeWindow>( window()->findNode( "IncomingMessages" ) );
	m_pShipStatusText = WidgetCast<WindowText>( window()->findNode( "ShipStatusText" ) );
	m_pEnergyText = WidgetCast<WindowText>( window()->findNode( "EnergyText" ) );
	m_pEnergyBar = WidgetCast<BarHUD>( window()->findNode( "EnergyBar" ) );
	m_pHullText = WidgetCast<WindowText>( window()->findNode( "HullText" ) );
	m_pHullBar = WidgetCast<BarHUD>( window()->findNode( "HullBar" ) );
	m_pViewNavigation = WidgetCast<NodeWindow>( window()->findNode( "ViewNavigation" ) );
	m_pViewTactical = WidgetCast<NodeWindow>( window()->findNode( "ViewTactical" ) );
	//END_DATA_INIT}}

	for(int i=0;i<5;i++)
	{
		CharString tipButtonName;
		tipButtonName = CharString().format("ButtonTip%d",i+1);
		m_pButtonTip[i] = WidgetCast<WindowButton>( window()->findNode( tipButtonName ) );
		// hide all the tip buttons
		m_pButtonTip[i]->hideWindow();
	}

#ifdef _DEBUG
	m_pSettings = new Settings( "ClientD" );
#else
	m_pSettings = new Settings( "Client" );
#endif

	m_pDoc = WidgetCast<GameDocument>( document() );
	ASSERT( m_pDoc );

	// 
	// show help 
	m_pHelpWindow->showWindow( m_pSettings->get( "showHelp", 1 ) != 0 );

	m_HideTips = m_pSettings->get("hideTips",(dword)0) != 0;

	// load up viewed tips
	CharString tipKey;

	for(unsigned int i=0;i<TIP_LAST;i++)
	{
		tipKey = CharString().format("TipViewed_%d",i);
		unsigned int id = m_pSettings->get(tipKey,(dword)0);
		if(id != 0)
			m_ViewedTips.push(i);
	}

	// show the welcome tip
	addPotentialTip(TIP_WELCOME);
	// hide all sub windows
	m_pIncomingMessages->showWindow();
	m_pTargetFrame->hideWindow();
	m_pWindowTransferCredits->hideWindow();

	// hide all target buttons
	m_pButtonFollow->hideWindow();
	m_pButtonLoad->hideWindow();
	m_pButtonOrbit->hideWindow();
	m_pButtonDisband->hideWindow();
	m_pButtonScrap->hideWindow();
	m_pButtonContinue->hideWindow();
	m_pButtonPause->hideWindow();
	m_pButtonCamera->showWindow();
	m_pButtonJettison->hideWindow();
	m_pButtonLock->hideWindow();
	m_pButtonUnlock->hideWindow();
	m_pButtonTransferCredits->hideWindow();

	// start in tactical mode
	m_Mode = TACTICAL;
	m_pViewNavigation->hideWindow();
	m_pViewTactical->showWindow();
	m_pViewTactical->onActivate();
	m_pViewPlanet->hideWindow();

	// setup the hull bar
	m_pHullBar->setHeadColor( Color( 255, 0, 0), Color( 216, 228, 52) );
	m_pHullBar->setTailColor( Color( 255, 0, 0), Color( 47, 205, 24 ) );
	// setup the energy bar
	m_pEnergyBar->setHeadColor( Color( 255, 0, 0), Color( 123, 60, 230) );
	m_pEnergyBar->setTailColor( Color( 255, 0, 0), Color( 57, 215, 232 ) );

	m_pSignatureBar->setHeadColor( DARK_BLUE, SKYBLUE );
	m_pSignatureBar->setTailColor( DARK_BLUE, BLUE );

	m_CollisionCheck = 0.0f;
	m_CameraFromNavigation = false;

	// reset the camera time
	GameDocument::s_fCamera = 0.0f;
	// inform script we are entering the game
	m_pDoc->context()->scriptCall( "onTactical()" );

	// init the enhancement icons
	NounEnhancement::InitializeIcons();
	m_nRotatingEnhancementTick =0;
	m_CurrentEnhancement = 1;
}


WindowButton *ViewGame::getFreeTipButton()
{
	for(int j=0;j<5;j++)
	{
		if(m_pButtonTip[j]->visible() == false)
			return m_pButtonTip[j];
	}
	return NULL;
}
void ViewGame::checkForPendingTips()
{
	// how many tips do we have pending?
	int nPending = m_PendingTipList.size();
	// do we have any pending ?
	if(nPending == 0)
		return;

	// find a free button
	WindowButton *pFreeButton = getFreeTipButton();

	// if no free tip button, return
	if(pFreeButton == NULL)
		return;

	// add the last pending item
	TipHelpData *pTip = TipHelpSystem::GetTip(m_PendingTipList.last());
	m_PendingTipList.pop();
	pFreeButton->setTip(pTip->GetTipTitle());
	pFreeButton->showWindow(true);
	window()->playSound("NEWHELPTIP");
}

bool ViewGame::isTipPending(unsigned int a_id)
{
	for(int i=0;i<m_PendingTipList.size();i++)
	{
		if(m_PendingTipList[i] == a_id)
			return true;
	}
	return false;
}


void ViewGame::addPotentialTip(unsigned int a_id)
{
	// are tips on?
	if(m_HideTips)
		return;
	// first make sure this tip is not already being displayed
	for(int j=0;j<5;j++)
	{
		if(m_pButtonTip[j]->visible())
		{
			unsigned int id = TipHelpSystem::GetIDByTitle(m_pButtonTip[j]->tip());
			if(id == a_id)
				return;
		}
	}

	// make sure we have not already viewed this tip

	for(int i=0;i<m_ViewedTips.size();i++)
	{
		unsigned int id = m_ViewedTips[i];
		if(a_id == id)
			return;
	}

	// is this tip pending already?
	if(isTipPending(a_id) == false)
	{
		// add this tip to the pendingList
		m_PendingTipList.push(a_id);
	}
}

void ViewGame::addTip(unsigned int a_id)
{
	m_pViewGame->addPotentialTip(a_id);
}


void ViewGame::onDeactivate()
{

	m_pSettings->put( "showHelp", m_pHelpWindow->visible() ? 1 : 0 );

// save the viewed tips
	CharString tipKey;
	for(int i=0;i<m_ViewedTips.size();i++)
	{
		tipKey = CharString().format("TipViewed_%d",m_ViewedTips[i]);
		m_pSettings->put(tipKey,1);
	}

	// called before this view is destroyed
	m_ConfirmScrap = NULL;
	m_ConfirmDisband = NULL;
	m_ConfirmJettison = NULL;
	m_ConfirmUseStructure = NULL;
	m_ConfirmRemoveEnhancement = NULL;
	m_LastTarget = NULL;
}

// rotating enhancements change at this rate
const int ROTATING_ENHANCEMENT_RATE	= 2.0f;	


void ViewGame::onUpdate( float t )
{
	ASSERT( m_pDoc );

	GameDocument::s_fCamera += t;

	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );
	NounShip * pShip = m_pDoc->ship();
	if (! pShip )
		return;

	checkForPendingTips();

	// update buttons
	m_pButtonHelp->setTargetAlpha( m_pHelpWindow->visible() ? 1.0f : 0.35f );
	m_pButtonNavigation->setTargetAlpha( m_pViewNavigation->visible() ? 1.0f : 0.35f  );
	m_pButtonPlanet->setTargetAlpha( m_pViewPlanet->visible() ? 1.0f : 0.35f  );

	m_pButtonTarget->setButtonDown( m_ChatMode == TARGET  );
	m_pButtonYell->setButtonDown( m_ChatMode == YELL );
	m_pButtonFaction->setButtonDown( m_ChatMode == FACTION  );
	m_pButtonFleet->setButtonDown( m_ChatMode == FLEET );

	if ( m_pButtonRightConsole->buttonDown() )
	{
		// show hide target window
		Noun * pTarget = myTarget();
		if ( pTarget != NULL )
		{
			bool bIsShiftDown = Keyboard::shiftDown();

			// show the target window
			m_pTargetFrame->showWindow();
			// has the target changed, if so hide all buttons
			if ( pTarget != m_LastTarget )
			{
				// hide all buttons
				hideAllButtons( m_pLayoutTargetButtons );
				// set the last target
				m_LastTarget = pTarget;
			}
			
			// enable disable ship command buttons
			m_pButtonShadow->updateButton( pShip->canCommand( NounShip::SHADOW, pTarget ), 
				!pShip->isCommand( NounShip::SHADOW, pTarget ) );
			m_pButtonFollow->updateButton( pShip->canCommand( NounShip::FOLLOW, pTarget ), 
				!pShip->isCommand( NounShip::FOLLOW, pTarget ) );

			bool bCanOrbit = pShip->canCommand( NounShip::ORBIT, pTarget );
			if(bCanOrbit)
				addPotentialTip(TIP_ORBIT);
			m_pButtonOrbit->updateButton( bCanOrbit, 
				!pShip->isCommand( NounShip::ORBIT, pTarget ) );

			// show order buttons
			m_pButtonAttackMission->showWindow( false ); //pShip->canSendOrder( NounShip::ATTACK, pTarget ) );
			m_pButtonCaptureMission->showWindow( false ); //pShip->canSendOrder( NounShip::CAPTURE, pTarget ) );
			m_pButtonDefendMission->showWindow( false ); //pShip->canSendOrder( NounShip::DEFEND, pTarget ) );
			m_pButtonScoutMission->showWindow( false ); //pShip->canSendOrder( NounShip::RECON, pTarget ) );

			// camera is only allowed for friendly targets
			m_pButtonCamera->updateButton( pShip->isFriend( pTarget ) && pTarget->isRootNoun() );
			// show load button, enable window if item can actually be loaded
			m_pButtonLoad->updateButton( VerbLoad::canLoad( pTarget, pShip ) );
			// show jettison button for any cargo that can be jettisoned
			m_pButtonJettison->updateButton( VerbUnload::canUnload( pShip, pTarget, pShip ) );

			// get the zone parent of our target
			Noun * pZoneParent = pTarget->zoneParent();
			// show next/prev buttons for current target
			if ( !m_pPopupTargetButtons->up() )
			{
				m_pButtonUpTarget->showWindow( pTarget != pZoneParent );
				m_pButtonNextTarget->showWindow( (pTarget == pZoneParent && pTarget->childCount() > 0) || 
					(pTarget != pZoneParent && pTarget->zone() != NULL) );
			}
			
			// update the target description
			CharString sTargetinfo;
			float targetDistance = (pShip->worldPosition() - pTarget->worldPosition()).magnitude();
			sTargetinfo += CharString().format( "%s<X;130>%.1f gu\n", pTarget->name(), targetDistance );

			if ( WidgetCast<NounPlanet>( pTarget ) )
			{
				NounPlanet * pPlanet = (NounPlanet *)pTarget;
				sTargetinfo += pPlanet->status();

				// show lock buttons
				m_pButtonLock->updateButton( VerbLockPlanet::canLock( pPlanet, pShip ) );
				m_pButtonUnlock->updateButton( VerbLockPlanet::canUnlock( pPlanet, pShip) );
			}
			else if ( WidgetCast<NounShip>( pTarget ) )
			{
				NounShip * pTargetShip = (NounShip *)pTarget;
				sTargetinfo += pTargetShip->status();
				if ( pShip->isFriend( pTargetShip ) && pTargetShip->order() != NounShip::NOORDER )
					sTargetinfo += CharString().format("\n%s", pTargetShip->orderString() );

				// update rotating enancement timer

				m_nRotatingEnhancementTick += t;
				if ( m_nRotatingEnhancementTick > ROTATING_ENHANCEMENT_RATE )
				{
					m_nRotatingEnhancementTick = 0;
					m_CurrentEnhancement++;
					if(m_CurrentEnhancement > pTargetShip->enhancementCount())
						m_CurrentEnhancement = 1;
				}
				if(pTargetShip->enhancementCount() > 0)
				{
					if(m_CurrentEnhancement > pTargetShip->enhancementCount())
						m_CurrentEnhancement = 1;

					sTargetinfo += CharString().format("\nEnhancements: (%d of %d)\n<color;%6.6x>%s</color>",
							m_CurrentEnhancement,pTargetShip->enhancementCount(),
							pTargetShip->enhancement(m_CurrentEnhancement)->color().RGB(),
							pTargetShip->enhancement(m_CurrentEnhancement)->GetName());
				}
				else
				{
					sTargetinfo += CharString().format("\nEnhancements: (None)");
				}
				
				m_pButtonCancelOrder->updateButton( pTargetShip->canOrder( NounShip::NOORDER, NULL, pShip ) );
				// show the transfer credits button and window, hide if the confirmation window is being displayed
				//m_pButtonTransferCredits->updateButton( VerbTransferCredits::canTransferCredits( pShip, pTargetShip, 1) );
				//m_pWindowTransferCredits->showWindow( m_pEditTransferCredits->editing() );
			}
			else if ( WidgetCast<NounUnit>( pTarget ) )
			{
				NounUnit * pUnit = (NounUnit *)pTarget;
				sTargetinfo += pUnit->status();
			
				m_pButtonDisband->updateButton( VerbDisband::canDisband( pUnit, pShip ) );
				bool bCanOrder = VerbOrderUnit::canOrder( pUnit, pShip );
				m_pButtonOrderAttack->updateButton( bCanOrder );
				m_pButtonOrderDefend->updateButton( bCanOrder );
				m_pButtonOrderRaze->updateButton( bCanOrder );
			}
			else if ( WidgetCast<NounJumpGate>( pTarget ) )
			{
				NounJumpGate * pGate = (NounJumpGate *)pTarget;
				sTargetinfo += pGate->status();
			}
			else if ( WidgetCast<NounGadget>( pTarget ) )
			{
				NounGadget * pGadget = (NounGadget *)pTarget;
				sTargetinfo += pGadget->status();
				sTargetinfo += CharString().format("\n%s", pGadget->description() );

				// is this gadget attached to this ship
				if ( pGadget->parentNoun() == pShip )
				{
					bool isBeamWeapon = WidgetCast<GadgetBeamWeapon>( pGadget ) != NULL;
					bool isGadgetDamaged = pGadget->damage() > 0;
					bool isGadgetSlot = WidgetCast<GadgetSlot>( pGadget ) != NULL;
					bool isUseMode = pGadget->useModeCount() > 1;

					m_pButtonAutoDefense->updateButton( isBeamWeapon );
					m_pButtonRepairLast->updateButton( isGadgetDamaged );
					m_pButtonRepairNow->updateButton( isGadgetDamaged );
					m_pButtonNext->updateButton( isUseMode );
					m_pButtonPrev->updateButton( isUseMode );
				}

			}
			else if ( WidgetCast<NounStructure>( pTarget ) )
			{
				NounStructure * pStructure = (NounStructure *)pTarget;
				sTargetinfo += pStructure->status(); 

				bool bCanPause = VerbSetStructureActive::canPauseStructure( pStructure, pShip );
				bool bCanContinue = VerbSetStructureActive::canContinueStructure( pStructure, pShip );
				bool bCanUsestructure = VerbUseStructure::canUse( pStructure, pShip );
				bool bCanScrap = VerbScrap::canScrap( pStructure, pShip );

				m_pButtonScrap->updateButton(bCanScrap );
				m_pButtonContinue->updateButton( bCanContinue );
				m_pButtonPause->updateButton(bCanPause );
				m_pButtonUseStructure->updateButton( bCanUsestructure );
			}
			else if ( WidgetCast<CargoEnhancement>( pTarget ) )
			{
				sTargetinfo += CharString().format("\n%s", ((CargoEnhancement *)pTarget)->status() );
				bool bCanApplyEnhancement = VerbApplyEnhancement::canApply((CargoEnhancement *)pTarget,pShip);
				if(((CargoEnhancement *)pTarget)->enhancement()->applyType() == NounEnhancement::ApplyType::AT_ATTACH)
					m_pButtonApplyEnhancement->setTip("Attach Enhancement");
				else
					m_pButtonApplyEnhancement->setTip("Use Item");
				m_pButtonApplyEnhancement->updateButton(bCanApplyEnhancement);
			}
			else if ( WidgetCast<CargoGadget>( pTarget ) )
			{
				NounGadget * pGadget = ((CargoGadget *)pTarget)->gadget();
				sTargetinfo += CharString().format("\n%s", pGadget->description() );
			}

			m_pTargetDescription->setText( sTargetinfo );
		}
		else
			m_pTargetFrame->hideWindow();
	}


	// update the energy bar
	m_pEnergyBar->setPosition( pShip->energyRatio() );
	m_pEnergyText->setText( CharString().format( "Energy: %.1f", float( pShip->energy() ) / 1000.0f ) );
	// update the hull bar
	m_pHullBar->setPosition( pShip->damageRatioInv() );
	m_pHullText->setText( CharString().format("Hull: %d%%", int( pShip->damageRatioInv() * 100 ) ) );
	// update the signature bar
	m_pSignatureBar->setPosition( Clamp( pShip->signature(), 0.0f, 50.0f ) / 50.0f  );
	m_pSignatureText->setText( CharString().format( "Signature: %.1f", pShip->signature() ) );

	// update the ship status line
	dword tick = pContext->tick();

	CharString sShipStatus;
	sShipStatus.format("%2.2u:%2.2u:%2.2u", 
		tick / TICKS_PER_HOUR, 
		(tick / TICKS_PER_MINUTE) % 60, 
		(tick / TICKS_PER_SECOND) % 60 );

	if ( pContext->timeLimit() > 0 )
	{
		dword remain = pContext->timeLimit() - tick;
		sShipStatus += CharString().format(" - %2.2u:%2.2u:%2.2u", 
			remain / TICKS_PER_HOUR, 
			(remain / TICKS_PER_MINUTE) % 60, 
			(remain / TICKS_PER_SECOND) % 60 );
	}
	//sShipStatus += CharString().format(" - Credits: %s", FormatNumber<char,int>( pShip->credits() ) );

	if ( pShip->command() != NounShip::NOCOMMAND )
		sShipStatus += CharString().format("<X;0;Y;13>%s", pShip->commandString() );		// display the current helm command
	m_pShipStatusText->setText( sShipStatus );

	// check for a new order
	static NounShip::Order	lastOrder;
	static Noun *			lastOrderTarget;
	if ( pShip->order() != lastOrder || pShip->orderTarget() != lastOrderTarget )
	{
		// new order received, play sound
		lastOrder = pShip->order();
		lastOrderTarget = pShip->orderTarget();

		if ( pShip->order() != NounShip::NOORDER )
			window()->playSound( "ORDERRECEIVED" );
	}

	// check for collision
	m_CollisionCheck += t;
	if ( m_CollisionCheck > CHECK_FOR_COLLISION_TIME )
	{
		m_CollisionCheck = 0.0f;

		Vector3 origin( pShip->worldPosition() );
		Vector3 direction( pShip->worldVelocity() * COLLISION_WARNING_TIME );

		for(int i=0;i<pShip->contactCount();i++)
		{
			Noun * pContact = pShip->contact( i );
			if ( WidgetCast<NounPlanet>( pContact ) == NULL && WidgetCast<NounStar>( pContact ) == NULL )
				continue;

			Vector3 intersect;
			if ( pContact->intersect( origin, direction, intersect ) )
			{
				window()->playSound( "CollisionAlert" );
				break;
			}
		}
	}
}

bool ViewGame::onMessage( const Message & msg )
{
	ASSERT( m_pDoc );

	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );

	//{{BEGIN_MSG_MAP
	MESSAGE_MAP( WB_BUTTONUP, 2369808366, onButtonRemoveEnhancement);
	MESSAGE_MAP( WB_BUTTONUP, 3547696933, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547696965, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547696997, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547695685, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547695717, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547696005, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547696037, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547696069, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547696101, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547695877, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547695909, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 3547695941, onButtonEnhUp);
	MESSAGE_MAP( WB_BUTTONUP, 2648656488, onButtonShowEnhancements);
	MESSAGE_MAP( WB_BUTTONUP, 3369159190, onButtonApplyEnhancement);
	MESSAGE_MAP( WB_BUTTONUP, 2397306610, onTipHelpOK);
	MESSAGE_MAP( WB_BUTTONUP, 1483157523, onButtonTip5);
	MESSAGE_MAP( WB_BUTTONUP, 1483157555, onButtonTip4);
	MESSAGE_MAP( WB_BUTTONUP, 1483157715, onButtonTip3);
	MESSAGE_MAP( WB_BUTTONUP, 1483157747, onButtonTip2);
	MESSAGE_MAP( WB_BUTTONUP, 1483157651, onButtonTip1);
	MESSAGE_MAP( WB_BUTTONUP, 1947446322, onMessageBoxCANCEL);
	MESSAGE_MAP( WB_BUTTONUP, 857413197, onMessageBoxOK);
	MESSAGE_MAP( WB_BUTTONUP, 1297067625, onButtonAbortOrder);
	MESSAGE_MAP( WB_BUTTONUP, 1402546913, onButtonCancelOrder);
	MESSAGE_MAP( WB_BUTTONUP, 2276611452, onButtonOrderRaze);
	MESSAGE_MAP( WB_BUTTONUP, 1083490971, onButtonOrderDefend);
	MESSAGE_MAP( WB_BUTTONUP, 599193466, onButtonOrderAttack);
	MESSAGE_MAP( WB_BUTTONUP, 1000934661, onButtonTargetYard);
	MESSAGE_MAP( WB_BUTTONUP, 993922821, onButtonTargetPort);
	MESSAGE_MAP( WB_BUTTONUP, 203370444, onButtonTargetSupply);
	MESSAGE_MAP( WB_BUTTONUP, 1006793111, onButtonTargetJumpGate);
	MESSAGE_MAP( WB_BUTTONUP, 3041943984, onButtonTargetDistress);
	MESSAGE_MAP( WB_BUTTONUP, 378576430, onButtonTargetFriendly);
	MESSAGE_MAP( WB_BUTTONUP, 1306136455, onButtonTargetEnemy);
	MESSAGE_MAP( WB_BUTTONUP, 1609169792, onButtonShadow);
	MESSAGE_MAP( WB_BUTTONUP, 4048941282, onButtonScoutMission);
	MESSAGE_MAP( WB_BUTTONUP, 3487455382, onButtonDefendMission);
	MESSAGE_MAP( WB_BUTTONUP, 310826742, onButtonCaptureMission);
	MESSAGE_MAP( WB_BUTTONUP, 3603953565, onButtonAttackMission);
	MESSAGE_MAP( WB_BUTTONDOWN, 2362987489, onButtonTarget);
	MESSAGE_MAP( WB_BUTTONDOWN, 1488015155, onButtonYell);
	MESSAGE_MAP( WB_BUTTONDOWN, 3090946401, onButtonFaction);
	MESSAGE_MAP( WB_BUTTONDOWN, 683493611, onButtonFleet);
	MESSAGE_MAP( WB_BUTTONUP, 1366481305, onButtonNextTarget);
	MESSAGE_MAP( WB_BUTTONUP, 3963033914, onButtonUpTarget);
	MESSAGE_MAP( WB_BUTTONUP, 1505827891, onButtonNext);
	MESSAGE_MAP( WB_BUTTONUP, 1479207027, onButtonPrev);
	MESSAGE_MAP( WB_BUTTONUP, 2981508253, onButtonRepairNow);
	MESSAGE_MAP( WB_BUTTONUP, 920750390, onButtonRepairLast);
	MESSAGE_MAP( WB_BUTTONUP, 29309963, onButtonAutoDefense);
	MESSAGE_MAP( WB_BUTTONUP, 3103999357, onButtonUseStructure);
	MESSAGE_MAP( WE_EDITDONE, 1602461257, onEditTransferCredits);
	MESSAGE_MAP( WB_BUTTONUP, 2673418001, onButtonTransferCredits);
	MESSAGE_MAP( WB_BUTTONUP, 2548880352, onButtonPlanet);
	MESSAGE_MAP( WB_BUTTONUP, 3543943169, onButtonUnlock);
	MESSAGE_MAP( WB_BUTTONUP, 1508144083, onButtonLock);
	MESSAGE_MAP( WB_BUTTONUP, 3347918290, onButtonJettison);
	MESSAGE_MAP( WB_BUTTONUP, 1294536004, onButtonCamera);
	MESSAGE_MAP( WB_BUTTONUP, 1199820260, onButtonContinue);
	MESSAGE_MAP( WB_BUTTONUP, 73732811, onButtonPause);
	MESSAGE_MAP( WE_EDITDONE, 3966988240, onChatEdit);
	MESSAGE_MAP( WB_BUTTONUP, 2572688435, onButtonDisband);
	MESSAGE_MAP( WB_BUTTONUP, 38197355, onButtonScrap);
	MESSAGE_MAP( WB_BUTTONUP, 1508145715, onButtonLoad);
	MESSAGE_MAP( WB_BUTTONUP, 996079851, onButtonOrbit);
	MESSAGE_MAP( WB_BUTTONUP, 289274757, onButtonFollow);
	MESSAGE_MAP( WB_BUTTONUP, 2434104373, onButtonNavigation);
	MESSAGE_MAP( WB_BUTTONUP, 1503743155, onButtonHelp);
	//END_MSG_MAP}}

	switch( msg.message )
	{
	case HM_CHAR:
		switch( msg.wparam )
		{
		case HK_RETURN:
			if (! m_pButtonSendChat->buttonDown() )
				m_pButtonSendChat->onButtonDown();

			m_pChatEdit->onBeginEdit();
			return true;
		}
		break;
	case HM_KEYDOWN:
		switch( msg.wparam )
		{
		case HK_ESCAPE:
			if ( m_Mode != TACTICAL )
			{
				changeMode( TACTICAL );
				return true;
			}
			if ( m_pDoc->focus() != m_pDoc->ship() )
			{
				// restore focus back to the ship
				m_pDoc->setFocus( m_pDoc->ship() );
				GameDocument::s_fCamera = 0.0f;
				return  true;
			}

			m_pDoc->setScene( "Main" );
			return true;
		}
		break;
	case HM_KEYUP:
		break;
	}

	return false;
}

void ViewGame::onDocumentUpdate()
{
	// document data has changed, update this view if needed
}

void ViewGame::onRender( RenderContext & context, const RectInt & window )
{}

//----------------------------------------------------------------------------


bool ViewGame::onButtonHelp(const Message & msg)
{
	// show/hide the help window
	if ( m_pHelpWindow->visible() )
		m_pHelpWindow->hideWindow();
	else
		m_pHelpWindow->showWindow();
	return true;
}

bool ViewGame::onButtonNavigation(const Message & msg)
{
	if ( m_Mode != NAVIGATION )
		changeMode( NAVIGATION );
	else
		changeMode( TACTICAL );
	return true;
}

bool ViewGame::onButtonPlanet(const Message & msg)
{
	if ( m_Mode != PLANET )
		changeMode( PLANET );
	else
		changeMode( TACTICAL );
	return true;
}

bool ViewGame::onButtonFollow(const Message & msg)
{
	m_pDoc->ship()->verbCommand( NounShip::FOLLOW, myTarget() );
	return true;
}

bool ViewGame::onButtonOrbit(const Message & msg)
{
	m_pDoc->ship()->verbCommand( NounShip::ORBIT, myTarget() );
	return true;
}

bool ViewGame::onButtonShadow(const Message & msg)
{
	m_pDoc->ship()->verbCommand( NounShip::SHADOW, myTarget() );
	return true;
}

bool ViewGame::onButtonLoad(const Message & msg)
{
	NounShip * pShip = m_pDoc->ship();
	Noun * pLoad = myTarget();

	// if loading from a port, just call use structur, so resources get updated properly
	// still using the CanLoad call for the button availabilty since it checks cargo room and everything
	if(WidgetCast<StructurePort>(pLoad))
	{
		StructurePort *pStructure = WidgetCast<StructurePort>(pLoad);
		if(VerbUseStructure::canUse( pStructure, pShip ))
			Verb::Ref( new VerbUseStructure( pStructure, m_pDoc->ship()) );
	}
	else if ( VerbLoad::canLoad( pLoad, pShip ) )
	{
		// send the verb to load the object
		Verb::Ref( new VerbLoad( pShip, pLoad ) );

		// if loading a unit from the planet, automatically select any other friendly unit in the same hex...
		Noun * pParent = pLoad->parentNoun();
		if ( WidgetCast<NounPlanet>( pParent ) && WidgetCast<NounUnit>( pLoad ) )
		{
			int nHex = ((NounUnit *)pLoad)->hex();
			for(int i=0;i<pParent->childCount();++i)
			{
				NounUnit * pUnit = WidgetCast<NounUnit>( pParent->child(i) );
				if ( pUnit && pUnit != pLoad && pUnit->hex() == nHex && VerbLoad::canLoad( pUnit, pShip ) )
				{
					m_pDoc->setTarget( pUnit );
					return true;
				}
			}
		}
		
		m_pDoc->setTarget( pParent );
	}

	return true;
}

bool ViewGame::onButtonScrap(const Message & msg)
{
	NounStructure * pScrap = WidgetCast<NounStructure>( myTarget() );
	if ( pScrap != NULL )
	{
		if ( pScrap != m_ConfirmScrap )
		{
			m_pDoc->pushChat( CharString().format( "<color;ffffff>Construction: Confirm scrap of %s...</color>", pScrap->name()) );
			m_ConfirmScrap = pScrap;
		}
		else
		{
			m_pDoc->setTarget( pScrap->parentNoun() );
			Verb::Ref( new VerbScrap( pScrap, m_pDoc->ship()) );
		}
	}
	return true;
}

bool ViewGame::onButtonDisband(const Message & msg)
{
	NounUnit * pDisband = WidgetCast<NounUnit>( myTarget() );
	if ( pDisband != NULL )
	{
		if ( pDisband != m_ConfirmDisband )
		{
			m_pDoc->pushChat( CharString().format( "<color;ffffff>SERVER: Confirm disband of %s...</color>", pDisband->name()) );
			m_ConfirmDisband = pDisband;
		}
		else
		{
			m_pDoc->setTarget( pDisband->parentNoun() );
			Verb::Ref( new VerbDisband( pDisband, m_pDoc->ship()) );
		}

	}
	return true;
}

bool ViewGame::onChatEdit(const Message & msg)
{
	CharString send( m_pChatEdit->text() );
	if ( send.length() > 0 )
	{
		if ( send[ 0 ] != '/' )
		{
			switch( m_ChatMode )
			{
			case FACTION:
				send.format( "/faction %s", send );
				break;
			case FLEET:
				send.format( "/team %s", send );
				break;
			case YELL:
				send.format( "/yell %s", send );
				break;
			case TARGET:
				send.format( "/target %s", send );
				break;
			}
		}

		m_pDoc->sendChat( send );
		m_pChatEdit->setText( "" );
	}

	// hide the communications window
	if ( m_pButtonSendChat->buttonDown() )
		m_pButtonSendChat->onButtonUp();

	return true;
}

bool ViewGame::onButtonPause(const Message & msg)
{
	NounStructure * pStructure = WidgetCast<NounStructure>( myTarget() );
	if ( pStructure != NULL )
		Verb::Ref( new VerbSetStructureActive( pStructure, m_pDoc->ship(), false ) );

	return true;
}

bool ViewGame::onButtonContinue(const Message & msg)
{
	NounStructure * pStructure = WidgetCast<NounStructure>( myTarget() );
	if ( pStructure != NULL )
		Verb::Ref( new VerbSetStructureActive( pStructure, m_pDoc->ship(), true ) );

	return true;
}

bool ViewGame::onButtonCamera(const Message & msg)
{
	if ( m_pDoc->focus() != myTarget()  )
	{
		// change to tactical mode
		if ( m_Mode != TACTICAL )
			changeMode( TACTICAL );

		m_pDoc->setFocus( myTarget() );
		GameDocument::s_fCamera = 0.0f;

		return true;
	}

	m_pDoc->setFocus( m_pDoc->ship() );
	GameDocument::s_fCamera = 0.0f;
	return true;
}

bool ViewGame::onButtonJettison(const Message & msg)
{
	Noun * pJettison = myTarget();
	if ( pJettison != NULL )
	{
		if ( pJettison != m_ConfirmJettison )
		{
			m_pDoc->pushChat( CharString().format( "<color;ffffff>Cargo: Confirm jettison of %s...", pJettison->name()) );
			m_ConfirmJettison = pJettison;
		}
		else
		{
			m_pDoc->setTarget( pJettison );
			m_pDoc->ship()->verbJettison( pJettison );
		}
	}
	return true;
}

bool ViewGame::onButtonLock(const Message & msg)
{
	NounPlanet * pPlanet = WidgetCast<NounPlanet>( myTarget() );
	if ( VerbLockPlanet::canLock( pPlanet, m_pDoc->ship() ) )
		Verb::Ref( new VerbLockPlanet( pPlanet, m_pDoc->ship(), true) );

	return true;
}

bool ViewGame::onButtonUnlock(const Message & msg)
{
	NounPlanet * pPlanet = WidgetCast<NounPlanet>( myTarget() );
	if ( VerbLockPlanet::canUnlock( pPlanet, m_pDoc->ship() ) )
		Verb::Ref( new VerbLockPlanet( pPlanet, m_pDoc->ship(), false) );

	return true;
}

bool ViewGame::onButtonTransferCredits(const Message & msg)
{
	m_pWindowTransferCredits->showWindow();
	m_pEditTransferCredits->onBeginEdit();
	return true;
}

bool ViewGame::onEditTransferCredits(const Message & msg)
{
	//int credits = strtol( m_pEditTransferCredits->text(), NULL, 10 );

	//NounShip * pSrc = m_pDoc->ship();
	//NounShip * pDst = WidgetCast<NounShip>( myTarget() );
	//if ( VerbTransferCredits::canTransferCredits( pSrc, pDst, credits ) )
	//	Verb::Ref( new VerbTransferCredits( pSrc, pDst, credits) );
	//
	//m_pWindowTransferCredits->hideWindow();
	return true;
}

bool ViewGame::onButtonUseStructure(const Message & msg)
{
	NounStructure * pStructure = WidgetCast<NounStructure>( myTarget() );
	if ( pStructure != NULL )
	{
		// does using this structure require confirmation?
		if ( pStructure->useConfirm( m_pDoc->ship() ) )
		{
			if ( m_ConfirmUseStructure != pStructure )
			{
				// yes, confirm the use of this structure by the players ship
				m_pDoc->pushChat( CharString().format( "%s, execute command again...", 
					pStructure->useConfirmMessage( m_pDoc->ship() )) );
				m_ConfirmUseStructure = pStructure;

				return true;
			}
		}

		// use structure without confirmation
		Verb::Ref( new VerbUseStructure( pStructure, m_pDoc->ship()) );
		return true;
	}

	return true;
}


//----------------------------------------------------------------------------

Noun * ViewGame::myTarget() const
{
	Noun * pTarget = m_pDoc->target();
	if ( WidgetCast<NounDropTarget>( pTarget ) )
		pTarget = ((NounDropTarget *)pTarget)->planet();

	return pTarget;
}

NounGadget * ViewGame::myGadgetTarget() const
{
	NounGadget * pGadget = WidgetCast<NounGadget>( m_pDoc->target() );
	if ( pGadget != NULL && pGadget->parentNoun() == m_pDoc->ship() )
		return pGadget;

	return NULL;
}

void ViewGame::changeMode( Mode mode )
{
	if ( m_Mode != mode )
	{
		// switch the mode
		m_Mode = mode;
		// reset the camera animation time
		GameDocument::s_fCamera = 0.0f;

		// always restore focus to the players ship when they change modes
		m_pDoc->setFocus( m_pDoc->ship() );

		// show/hide windows based on the mode
		switch( m_Mode )
		{
		case TACTICAL:
			m_pViewNavigation->hideWindow();
			m_pViewTactical->showWindow();
			m_pViewPlanet->hideWindow();
			//window()->playSound( "TACTICAL" );
			break;
		case NAVIGATION:
			m_pViewTactical->hideWindow();
			m_pViewNavigation->showWindow();
			m_pViewPlanet->hideWindow();
			//window()->playSound( "NAVIGATION" );
			break;
		case PLANET:
			m_pViewTactical->hideWindow();
			m_pViewNavigation->hideWindow();
			m_pViewPlanet->showWindow();
			break;
		}
	}
}

//----------------------------------------------------------------------------

void ViewGame::hideAllButtons( BaseNode * pNode )
{
	// check if this node is a button, if so then hide it
	WindowButton * pButton = WidgetCast<WindowButton>( pNode );
	if ( pButton != NULL )
		pButton->hideWindow();

	// recurse into all children
	for(int i=0;i<pNode->childCount();i++)
		hideAllButtons( pNode->child(i) );
}

//----------------------------------------------------------------------------

bool ViewGame::onButtonAutoDefense(const Message & msg)
{
	Verb::Ref( new VerbUseSingleGadget( myGadgetTarget(), NULL, true ) );
	return true;
}

bool ViewGame::onButtonRepairLast(const Message & msg)
{
	Verb::Ref( new VerbRepairGadget( myGadgetTarget(), NounShip::LAST ) );
	return true;
}

bool ViewGame::onButtonRepairNow(const Message & msg)
{
	Verb::Ref( new VerbRepairGadget( myGadgetTarget(), NounShip::NOW ) );
	return true;
}

bool ViewGame::onButtonPrev(const Message & msg)
{
	NounGadget * pGadget = myGadgetTarget();
	ASSERT( pGadget );

	int prevMode = pGadget->useMode() - 1;
	if ( prevMode < 0 )
		prevMode = pGadget->useModeCount() - 1;

	Verb::Ref( new VerbUseMode( pGadget, prevMode ) );
	return true;
}

bool ViewGame::onButtonNext(const Message & msg)
{
	NounGadget * pGadget = m_pDoc->gadgetTarget();
	ASSERT( pGadget );

	int nextMode = (pGadget->useMode() + 1) % pGadget->useModeCount();
	Verb::Ref( new VerbUseMode( pGadget, nextMode ) );
	return true;
}

bool ViewGame::onButtonUpTarget(const Message & msg)
{
	Noun * pTarget = myTarget();
	if ( pTarget != NULL )
		m_pDoc->setTarget( pTarget->parentNoun() );
	return true;
}

bool ViewGame::onButtonNextTarget(const Message & msg)
{
	Noun * pTarget = myTarget();
	if ( pTarget != NULL )
	{
		Noun * pParent = pTarget->zoneParent();
		if ( pParent != NULL )
		{
			GameContext * pContext = m_pDoc->context();
			ASSERT( pContext );
			NounShip * pShip = m_pDoc->ship();
			if (! pShip )
				return true;

			bool bLastFound = false;
			if ( pParent == pTarget )
				bLastFound = true;

			for(int i=0;i<pParent->childCount();i++)
			{
				Noun * pChild = WidgetCast<Noun>( pParent->child(i) );
				if ( pChild != NULL )
				{
					if ( !bLastFound && pChild == pTarget )
					{
						// found our previous target in the child list of the zone parent
						bLastFound = true;
					}
					else if ( bLastFound && pShip->validateTarget( pChild ) )
					{
						m_pDoc->setTarget( pChild );
						return true;
					}
				}
			}

			// no additional children objects found, set target back to the parent object
			m_pDoc->setTarget( pParent );
		}
	}
	return true;
}

bool ViewGame::onButtonFleet(const Message & msg)
{
	m_ChatMode = FLEET;
	return true;
}

bool ViewGame::onButtonFaction(const Message & msg)
{
	m_ChatMode = FACTION;
	return true;
}

bool ViewGame::onButtonYell(const Message & msg)
{
	m_ChatMode = YELL;
	return true;
}

bool ViewGame::onButtonTarget(const Message & msg)
{
	m_ChatMode = TARGET;
	return true;
}

bool ViewGame::onButtonAttackMission(const Message & msg)
{
	m_pDoc->ship()->sendOrder( NounShip::ATTACK, m_pDoc->target() );
	return true;
}

bool ViewGame::onButtonCaptureMission(const Message & msg)
{
	m_pDoc->ship()->sendOrder( NounShip::CAPTURE, m_pDoc->target() );
	return true;
}

bool ViewGame::onButtonDefendMission(const Message & msg)
{
	m_pDoc->ship()->sendOrder( NounShip::DEFEND, m_pDoc->target() );
	return true;
}

bool ViewGame::onButtonScoutMission(const Message & msg)
{
	m_pDoc->ship()->sendOrder( NounShip::RECON, m_pDoc->target() );
	return true;
}

bool ViewGame::onButtonCancelOrder(const Message & msg)
{
	NounShip * pShip = WidgetCast<NounShip>( m_pDoc->target() );
	if ( pShip != NULL && pShip->order() != NounShip::NOORDER )
		pShip->verbOrder( NounShip::NOORDER, NULL, m_pDoc->ship() );

	return true;
}

bool ViewGame::onButtonAbortOrder(const Message & msg)
{
	if ( m_pDoc->ship()->order() != NounShip::NOORDER )
		m_pDoc->ship()->verbOrder( NounShip::NOORDER, NULL );
	return true;
}

bool ViewGame::onButtonTargetEnemy(const Message & msg)
{
	NounShip * pShip = m_pDoc->ship();
	if (! pShip )
		return true;
	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );

	Noun *	bestTarget = NULL;
	float	bestRange = MAX_TARGET_RANGE;

	Array< GameContext::NounCollision > nouns;
	pContext->proximityCheck( pShip->worldPosition(), bestRange, nouns );

	for(int i=0;i<nouns.size();i++)
	{
		Noun * pContact = nouns[i].pNoun;

		NounShip * pShipContact = WidgetCast<NounShip>( pContact );
		if ( !pShip->validateTarget( pShipContact ) )
			continue;
		if ( !pShip->isEnemy( pShipContact ) )
			continue;
		
		float range = (pShip->worldPosition() - pShipContact->worldPosition()).magnitude();
		if ( range < bestRange )
		{
			bestTarget = pShipContact;
			bestRange = range;
		}
	}

	if ( bestTarget != NULL )
		m_pDoc->setTarget( bestTarget );
	else
		pShip->clientChat( CharString("<color;ffffff>Tactical: No Enemy ships detected.") );
	return true;
}

bool ViewGame::onButtonTargetFriendly(const Message & msg)
{
	NounShip * pShip = m_pDoc->ship();
	if (! pShip )
		return true;
	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );

	Noun *	bestTarget = NULL;
	float	bestRange = MAX_TARGET_RANGE;

	Array< GameContext::NounCollision > nouns;
	pContext->proximityCheck( pShip->worldPosition(), bestRange, nouns );

	for(int i=0;i<nouns.size();i++)
	{
		Noun * pContact = nouns[i].pNoun;

		NounShip * pShipContact = WidgetCast<NounShip>( pContact );
		if (! pShip->validateTarget( pShipContact ) )
			continue;
		if ( pShipContact == pShip )
			continue;		// don't target self
		if ( !pShip->isFriend( pShipContact ) )
			continue;		// don't target enemy
		
		float range = (pShip->worldPosition() - pShipContact->worldPosition()).magnitude();
		if ( range < bestRange )
		{
			bestTarget = pShipContact;
			bestRange = range;
		}
	}

	if ( bestTarget != NULL )
		m_pDoc->setTarget( bestTarget );
	else
		pShip->clientChat( CharString("<color;ffffff>Tactical: No Friendly ships detected.") );
	return true;
}

bool ViewGame::onButtonTargetDistress(const Message & msg)
{
	Noun * pDistress = m_pDoc->validateNoun( VerbDistress::s_LastDistress );

	if ( pDistress != NULL )
		m_pDoc->setTarget( pDistress );
	else
		m_pDoc->ship()->clientChat( CharString( "<color;ffffff>Comms: No Distress signal received...</color>" ) );

	return true;
}

bool ViewGame::onButtonTargetJumpGate(const Message & msg)
{
	NounShip * pShip = m_pDoc->ship();
	if (! pShip )
		return true;
	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );

	Noun *	bestTarget = NULL;
	float	bestRange = MAX_TARGET_RANGE;

	Array< GameContext::NounCollision > nouns;
	pContext->proximityCheck( pShip->worldPosition(), bestRange, nouns );

	for(int i=0;i<nouns.size();i++)
	{
		Noun * pContact = nouns[i].pNoun;

		NounJumpGate * pGate = WidgetCast<NounJumpGate>( pContact );
		if ( !pShip->validateTarget( pGate ) )
			continue;
		if ( !pShip->isFriend( pGate ) )
			continue;
	
		float range = (pShip->worldPosition() - pGate->worldPosition()).magnitude();
		if ( range < bestRange )
		{
			bestTarget = pGate;
			bestRange = range;
		}
	}

	if ( bestTarget != NULL )
		m_pDoc->setTarget( bestTarget );
	else
		pShip->clientChat( CharString( "<color;ffffff>Tactical: Jump Gate not found...</color>" ) );
	return true;
}

bool ViewGame::onButtonTargetSupply(const Message & msg)
{
	NounShip * pShip = m_pDoc->ship();
	if (! pShip )
		return true;
	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );

	Noun *	bestTarget = NULL;
	float	bestRange = MAX_TARGET_RANGE;

	Array< GameContext::NounCollision > nouns;
	pContext->proximityCheck( pShip->worldPosition(), bestRange, nouns );

	for(int i=0;i<nouns.size();i++)
	{
		Noun * pContact = nouns[i].pNoun;

		if ( !pShip->validateTarget( pContact ) )
			continue;
		if ( !pShip->isFriend( pContact ) )
			continue;

		bool valid = false;
		if ( WidgetCast<NounShip>( pContact ) != NULL )
		{
			if ( ((NounShip *)pContact)->type() == NounShip::SUPPLY || 
				((NounShip *)pContact)->type() == NounShip::STATION ||
				((NounShip *)pContact)->type() == NounShip::PLATFORM_SUPPLY )
				valid = true;
		}
		else if ( WidgetCast<NounPlanet>( pContact ) != NULL )
		{
			NounPlanet * pPlanet = (NounPlanet *)pContact;
			if ( (pPlanet->flags() & NounPlanet::FLAG_HAS_DEPOT) == 0 )
				continue;

			StructureDepot * pDepot = NULL;
			for(int j=0;pDepot == NULL && j<pPlanet->childCount();j++)
				pDepot = WidgetCast<StructureDepot>( pPlanet->child(j) );

			if ( pDepot != NULL )
				pContact = pDepot;
			else
				pContact = pPlanet;
			valid = true;
		}

		if ( valid )
		{
			float range = (pShip->worldPosition() - pContact->worldPosition()).magnitude();
			if ( range < bestRange )
			{
				bestTarget = pContact;
				bestRange = range;
			}
		}
	}

	if ( bestTarget != NULL )
		m_pDoc->setTarget( bestTarget );
	else
		pShip->clientChat( CharString("<color;ffffff>Tactical: Depot/Supply not found...</color>") );
	return true;
}

bool ViewGame::onButtonTargetPort(const Message & msg)
{
	NounShip * pShip = m_pDoc->ship();
	if (! pShip )
		return true;
	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );

	Noun *	bestTarget = NULL;
	float	bestRange = MAX_TARGET_RANGE;

	Array< GameContext::NounCollision > nouns;
	pContext->proximityCheck( pShip->worldPosition(), bestRange, nouns );

	for(int i=0;i<nouns.size();i++)
	{
		Noun * pContact = nouns[i].pNoun;

		NounPlanet * pPlanet = WidgetCast<NounPlanet>( pContact );
		if ( !pShip->validateTarget( pPlanet ) )
			continue;
		if ( !pShip->isFriend( pPlanet ) )
			continue;
		if ( (pPlanet->flags() & NounPlanet::FLAG_HAS_PORT) == 0 )
			continue;
		
		float range = (pShip->worldPosition() - pPlanet->worldPosition()).magnitude();
		if ( range < bestRange )
		{
			StructurePort * pPort = NULL;
			for(int j=0;pPort == NULL && j<pPlanet->childCount();j++)
				pPort = WidgetCast<StructurePort>( pPlanet->child(j) );

			if ( pPort != NULL )
				bestTarget = pPort;
			else
				bestTarget = pPlanet;
			bestRange = range;
		}
	}

	if ( bestTarget != NULL )
		m_pDoc->setTarget( bestTarget );
	else
		pShip->clientChat( CharString("<color;ffffff>Tactical: Starport not found...</color>") );
	return true;
}

bool ViewGame::onButtonTargetYard(const Message & msg)
{
	NounShip * pShip = m_pDoc->ship();
	if (! pShip )
		return true;
	GameContext * pContext = m_pDoc->context();
	ASSERT( pContext );

	Noun *	bestTarget = NULL;
	float	bestRange = MAX_TARGET_RANGE;

	Array< GameContext::NounCollision > nouns;
	pContext->proximityCheck( pShip->worldPosition(), bestRange, nouns );

	for(int i=0;i<nouns.size();i++)
	{
		Noun * pContact = nouns[i].pNoun;

		NounPlanet * pPlanet = WidgetCast<NounPlanet>( pContact );
		if ( !pShip->validateTarget( pPlanet ) )
			continue;
		if ( !pShip->isFriend( pPlanet ) )
			continue;
		if ( (pPlanet->flags() & NounPlanet::FLAG_HAS_SHIPYARD) == 0 )
			continue;
		
		float range = (pShip->worldPosition() - pPlanet->worldPosition()).magnitude();
		if ( range < bestRange )
		{
			StructureShipyard * pYard = NULL;
			for(int J=0;pYard == NULL && J<pPlanet->childCount();J++)
				pYard = WidgetCast<StructureShipyard>( pPlanet->child(J) );

			if ( pYard != NULL )
				bestTarget = pYard;
			else
				bestTarget = pPlanet;
			bestRange = range;
		}
	}

	if ( bestTarget != NULL )
		m_pDoc->setTarget( bestTarget );
	else
		pShip->clientChat( CharString("<color;ffffff>Tactical: Shipyard not found...</color>") );

	return true;
}

bool ViewGame::onButtonOrderAttack(const Message & msg)
{
	Verb::Ref( new VerbOrderUnit( (NounUnit *)myTarget(), NounUnit::ATTACK, NULL, m_pDoc->ship() ) );
	return true;
}

bool ViewGame::onButtonOrderDefend(const Message & msg)
{
	Verb::Ref( new VerbOrderUnit( (NounUnit *)myTarget(), NounUnit::HOLD, NULL, m_pDoc->ship() ) );
	return true;
}

bool ViewGame::onButtonOrderRaze(const Message & msg)
{
	Verb::Ref( new VerbOrderUnit( (NounUnit *)myTarget(), NounUnit::RAZE, NULL, m_pDoc->ship() ) );
	return true;
}

bool ViewGame::onMessageBoxOK(const Message & msg)
{
	// hide the window first, as the script may re-display the window again
	m_pMessageBox->hideWindow();
	// call the button script
	m_pDoc->context()->scriptCall( m_pMessageBoxOK->script() );
	return true;
}

bool ViewGame::onMessageBoxCANCEL(const Message & msg)
{
	// hide the window first, always
	m_pMessageBox->hideWindow();
	m_pDoc->context()->scriptCall(  m_pMessageBoxCANCEL->script() );
	return true;
}

//----------------------------------------------------------------------------
// EOF


bool ViewGame::onButtonTip1(const Message & msg)
{
	// find tip
	// TODO: Create a new WindowButton that i can use to hold the id of the tip that is contained in it
	// instead of finding the tip based on the tooltip
	unsigned int id = TipHelpSystem::GetIDByTitle(m_pButtonTip[0]->tip());
	if(id != 0)
	{
		TipHelpData *pTip = TipHelpSystem::GetTip(id);
		m_pTipHelpText->setText(pTip->GetTip());
		m_pTipHelpTitle->setText(pTip->GetTipTitle());
		m_pTipHelpBox->showWindow(true);
	}
	return true;
}
bool ViewGame::onButtonTip2(const Message & msg)
{
	unsigned int id = TipHelpSystem::GetIDByTitle(m_pButtonTip[1]->tip());
	if(id != 0)
	{
		TipHelpData *pTip = TipHelpSystem::GetTip(id);
		m_pTipHelpText->setText(pTip->GetTip());
		m_pTipHelpTitle->setText(pTip->GetTipTitle());
		m_pTipHelpBox->showWindow(true);
	}
	return true;
}
bool ViewGame::onButtonTip3(const Message & msg)
{
	unsigned int id = TipHelpSystem::GetIDByTitle(m_pButtonTip[2]->tip());
	if(id != 0)
	{
		TipHelpData *pTip = TipHelpSystem::GetTip(id);
		m_pTipHelpText->setText(pTip->GetTip());
		m_pTipHelpTitle->setText(pTip->GetTipTitle());
		m_pTipHelpBox->showWindow(true);
	}
	return true;
}
bool ViewGame::onButtonTip4(const Message & msg)
{
	unsigned int id = TipHelpSystem::GetIDByTitle(m_pButtonTip[3]->tip());
	if(id != 0)
	{
		TipHelpData *pTip = TipHelpSystem::GetTip(id);
		m_pTipHelpText->setText(pTip->GetTip());
		m_pTipHelpTitle->setText(pTip->GetTipTitle());
		m_pTipHelpBox->showWindow(true);
	}
	return true;
}
bool ViewGame::onButtonTip5(const Message & msg)
{
	unsigned int id = TipHelpSystem::GetIDByTitle(m_pButtonTip[4]->tip());
	if(id != 0)
	{
		TipHelpData *pTip = TipHelpSystem::GetTip(id);
		m_pTipHelpText->setText(pTip->GetTip());
		m_pTipHelpTitle->setText(pTip->GetTipTitle());
		m_pTipHelpBox->showWindow(true);
	}
	return true;
}

bool ViewGame::onTipHelpOK(const Message & msg)
{
	// find the button that had this title and hide it
	for(int i=0;i<5;i++)
	{
		unsigned int id1 = TipHelpSystem::GetIDByTitle(m_pButtonTip[i]->tip());
		unsigned int id2 = TipHelpSystem::GetIDByTitle(m_pTipHelpTitle->text());
		if(id1==id2)
		{
			m_pButtonTip[i]->hideWindow();
			m_ViewedTips.push(id1);
		}
	}
	m_pTipHelpBox->showWindow(false);
	return true;
}

bool ViewGame::onButtonShowEnhancements(const Message & msg)
{
	if ( m_pEnhancementWindow->visible() )
		m_pEnhancementWindow->hideWindow();
	else
		m_pEnhancementWindow->showWindow();
	return true;	

}

bool ViewGame::onButtonEnhUp(const Message & msg)
{
	m_ConfirmRemoveEnhancement = NULL;
	return m_pEnhancementWindow->onButtonUp(msg);
}


bool ViewGame::onButtonRemoveEnhancement(const Message & msg)
{
	ButtonEnhancement * pConfirm = WidgetCast<ButtonEnhancement>(m_pEnhancementWindow->getSelected() );
	if ( pConfirm != NULL )
	{
		if ( pConfirm != m_ConfirmRemoveEnhancement )
		{
			CharString sEnhName = pConfirm->enhancement()->GetName();
			m_pDoc->pushChat( CharString().format( "<color;ffffff>Enhancement: Confirm destruction of %s...</color>", sEnhName) );
			m_ConfirmRemoveEnhancement = pConfirm;
		}
		else
		{
			NounEnhancement *pEnh = m_pEnhancementWindow->getSelected()->enhancement();
			if(pEnh)
			{
				Verb::Ref( new VerbRemoveEnhancement( m_pDoc->ship(),pEnh));
			}
			m_ConfirmRemoveEnhancement = NULL;
			m_pEnhancementWindow->setSelected(NULL);
//			Verb::Ref( new VerbScrap( pScrap, m_pDoc->ship()) );
		}
	}
	return true;
}

bool ViewGame::onButtonApplyEnhancement(const Message & msg)
{
	CargoEnhancement * pCargo= WidgetCast<CargoEnhancement>( myTarget() );
	if(m_pDoc && m_pDoc->ship() && pCargo)
	{
		m_pDoc->ship()->applyEnhancement(pCargo);
		return true;
	}
	return false;
}

